package org.pinda.network;

import java.io.DataOutputStream;
import java.io.IOException;

import org.pinda.network.auth.PacketHandshake;
import org.pinda.network.auth.PacketHandshakeResponse;
import org.pinda.network.util.Stream;

public class PacketUtils {
	
	/**
	 * Sends a packet on the stream
	 * @param outStream the outStream to write on
	 * @param packet The packet to send
	 * @throws IOException thrown when a OutputStream exception has been thrown
	 */
	public static void writePacket(DataOutputStream outStream, IPacket packet) throws IOException {
		outStream.writeInt(packet.getLength() + 2);
		outStream.writeShort(packet.getId());
		packet.write(outStream);
	}
	
	/**
	 * Reads a packet form the stream
	 * @param inStream The stream to read from
	 * @return The packet read from the stream
	 * @throws IOException when an packet is invalid
	 */
	public static IPacket readPacket(ConnectionType connectionType, Stream inStream) throws IOException {
		int id = inStream.readShort();
		IPacket packet = createPacket(connectionType, id);
		if(packet == null)
			throw new IOException("Invalid Protocol Packet");
		packet.read(inStream);
		return packet;
	}
	
	/**
	 * A factory method to create the packets
	 * @param connectionType the type of connection
	 * @param id the id of the packet
	 * @return
	 */
	private static IPacket createPacket(ConnectionType connectionType, int id) {
		
		if(id <= 1) {
			switch(id) {
			case 0:
				return new PacketHandshake();
				
			case 1:
				return new PacketHandshakeResponse();
			}
		}
		
		switch(connectionType) {
		
		case GAME:
			switch(id) {
			}
			
		case SERVER_BROWSER:
			switch(id) {
			}
			
		case UPDATE:
			switch(id) {
			}
			
		default:
			return null;
		}
	}
	
	/**
	 * Writes a string on the output stream<br/>
	 * The string has a maximum length of 65536 characters
	 * @param outStream the output stream
	 * @param s the string
	 * @throws IOException when an outputStream IOException occurs
	 */
	public static void writeString(DataOutputStream outStream, String s) throws IOException {
		//Truncate if longer than an unsigned short
		if(s.length() > (2 << 16)) {
			s = s.substring(0, 2 << 16);
		}
		outStream.writeShort(s.length());
		for(char character : s.toCharArray()) {
			outStream.writeByte(character);
		}
	}
	
	/**
	 * Reads a string from the stream
	 * @param stream the stream to read from
	 * @return the read string
	 */
	public static String readString(Stream stream) {
		int length = stream.readShort();
		char[] characters = new char[length];
		for(int i = 0; i < characters.length; i++) {
			characters[i] = (char)stream.readByte();
		}
		return new String(characters);
	}
	
	/**
	 * Calculates the amount of bytes needed to send the string
	 * @param s the string to send
	 * @return the amount of bytes needed
	 */
	public static int packetLengthString(String s) {
		return (s.length() > 2 << 16) ? 2 + 2 << 16 : 2 + s.length();
	}
	
	public static void sleep(int ms) {
		try {
			Thread.sleep(ms);
		} catch (InterruptedException e) {
		}
	}

}
